namespace NHCodeFirst.FluentMapper
{
    using System;
    using System.Linq.Expressions;
    using Enums;
    using HbmModel;
    using Helpers;

    public class OneToOneMapper<TEntity>
    {
        private readonly OneToOne oneToOne;

        public OneToOneMapper(OneToOne oneToOne)
        {
            this.oneToOne = oneToOne;
        }

        public OneToOneMapper<TEntity> Formula(string value)
        {
            oneToOne.Formula = value;
            return this;
        }

        public OneToOneMapper<TEntity> Lazy(bool value)
        {
            oneToOne.Lazy = value.ToString().ToLower();
            return this;
        }

        public OneToOneMapper<TEntity> Cascade(OneCascade value)
        {
            switch (value)
            {
                case OneCascade.SaveUpdate:
                    oneToOne.Cascade = "save-update";
                    break;
                default:
                    oneToOne.Cascade = value.ToString().ToLower();
                    break;
            }
            return this;
        }

        public OneToOneMapper<TEntity> Fetch(Fetch value)
        {
            oneToOne.Fetch = value.ToString().ToLower();
            return this;
        }

        public OneToOneMapper<TEntity> PropertyRef<TProperty>(Expression<Func<TEntity,TProperty>> selector)
        {
            oneToOne.PropertyRef = new ExpressionHelper().GetPropertyName(selector);
            return this;
        }

        public OneToOneMapper<TEntity> Constrained(bool value)
        {
            oneToOne.Constrained = value.ToString().ToLower();
            return this;
        }

        public OneToOneMapper<TEntity> ForeignKey(string value)
        {
            oneToOne.ForeignKey = value;
            return this;
        }

        public OneToOneMapper<TEntity> EntityName(string value)
        {
            oneToOne.EntityName = value;
            return this;
        }

        public OneToOneMapper<TEntity> Access(Access access, Naming? namingStrategy = null)
        {
            return Access(access.ToString().ToLower(), namingStrategy);
        }

        public OneToOneMapper<TEntity> Access<T>(Naming? namingStrategy = null)
        {
            return Access(typeof(T).FullName, namingStrategy);
        }

        public OneToOneMapper<TEntity> Access(Type type, Naming? namingStrategy = null)
        {
            return Access(type.FullName, namingStrategy);
        }

        private OneToOneMapper<TEntity> Access(string access, Naming? naming)
        {
            oneToOne.Access = access;
            if (naming.HasValue)
                oneToOne.Access += "." + EnumsToHbmString.GetAccessNamingStrategy(naming.Value);
            return this;
        }

        public OneToOneMapper<TEntity> OuterJoin(OuterJoinStrategy value)
        {
            oneToOne.OuterJoin = value.ToString().ToLower();
            return this;
        }
    }
}